package com.ziyun.erp.modules.logistics.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.utility.JsonUtils;
import com.utility.New;
import com.utility.StringUtils;
import com.ziyun.erp.common.api.logistics.LogisticsSearchApi;
import com.ziyun.erp.common.api.logistics.LogisticsVo;
import com.ziyun.erp.common.e.DeleteEnum;
import com.ziyun.erp.common.e.logistics.LogisticFinanceStatusEnum;
import com.ziyun.erp.common.e.order.ProductionStatusEnum;
import com.ziyun.erp.common.e.order.ShipStatusEnum;
import com.ziyun.erp.common.utils.FileUtil;
import com.ziyun.erp.common.utils.UserUtils;
import com.ziyun.erp.modules.logistics.dto.ErpLogisticsDto;
import com.ziyun.erp.modules.logistics.dto.LogisticsImportDto;
import com.ziyun.erp.modules.logistics.dto.LogisticsPayDto;
import com.ziyun.erp.modules.logistics.entity.ErpLogisticsInforEntity;
import com.ziyun.erp.modules.logistics.entity.ErpLogisticsItemEntity;
import com.ziyun.erp.modules.logistics.entity.LogisticsTypeEntity;
import com.ziyun.erp.modules.logistics.service.ErpLogisticsInforService;
import com.ziyun.erp.modules.logistics.service.LogisticsTypeService;
import com.ziyun.erp.modules.logistics.vo.CostFormVo;
import com.ziyun.erp.modules.logistics.vo.ErpLogisticsVo;
import com.ziyun.erp.modules.order.entity.ErpOrderEntity;
import com.ziyun.erp.modules.order.entity.OrderInfoEntity;
import com.ziyun.erp.modules.order.service.ErpOrderLogService;
import com.ziyun.erp.modules.order.service.ErpOrderService;
import com.ziyun.erp.modules.order.service.OrderInfoService;
import com.ziyun.erp.modules.production.entity.ErpOrderItemEntity;
import com.ziyun.erp.modules.production.operate.ErpOrderStateContext;
import com.ziyun.erp.modules.production.operate.ProduceFinishState;
import com.ziyun.erp.modules.production.operate.ProducingState;
import com.ziyun.erp.modules.production.operate.entity.LogisticsStateEntity;
import com.ziyun.erp.modules.production.service.ErpOrderItemService;
import io.renren.common.exception.RRException;
import io.renren.common.utils.DateUtils;
import io.renren.common.utils.R;
import io.renren.common.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import io.renren.common.utils.PageUtils;

import com.ziyun.erp.modules.logistics.dao.ErpLogisticsDao;
import com.ziyun.erp.modules.logistics.entity.ErpLogisticsEntity;
import com.ziyun.erp.modules.logistics.service.ErpLogisticsService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;


/**
 * 订单物流信息
 *
 * @author guizhao
 * @email ...
 * @date 2018-08-31 10:12:35
 */
@Slf4j
@Service("erpLogisticsService")
public class ErpLogisticsServiceImpl extends ServiceImpl<ErpLogisticsDao, ErpLogisticsEntity> implements ErpLogisticsService{

    @Autowired
    private OrderInfoService orderInfoService;
    @Autowired
    private ErpOrderService erpOrderService;
    @Autowired
    private ErpOrderItemService erpOrderItemService;
    @Autowired
    private LogisticsTypeService logisticsTypeService;
    @Autowired
    private ErpLogisticsService erpLogisticsService;
    @Autowired
    private LogisticsSearchApi logisticsSearchApi;
    @Autowired
    private ErpLogisticsInforService erpLogisticsInforService;
    @Autowired
    private ErpOrderLogService erpOrderLogService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        int currPage = StringUtil.objToInt(params.get("page")) == null ? 1: StringUtil.objToInt(params.get("page"));
        int pageSize = StringUtil.objToInt(params.get("limit")) == null ? 25: StringUtil.objToInt(params.get("limit"));
        Page<ErpLogisticsVo> page = new Page<>(currPage,pageSize);

        int totalCounts = baseMapper.countsFinanceList(params);
        page.setTotal(totalCounts);

        List<ErpLogisticsVo> list = baseMapper.queryFinanceList((page.getCurrent()-1)*page.getSize(),page.getSize(),params);
        page.setRecords(list);
        return new PageUtils(page);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R saveOrderLogisticsInfo(ErpLogisticsDto erpLogisticsDto, String userId, String createName) {
        try {
            ErpOrderStateContext erpOrderStateContext = new ErpOrderStateContext(new ProduceFinishState(),
                    new LogisticsStateEntity(erpLogisticsDto)
            );
            R logistics = erpOrderStateContext.addLogistics(userId, createName);
            int code = (int) logistics.get("code");
            if (code == 500){
                return logistics;
            }
        }catch (Exception e){
            e.printStackTrace();
            throw new RRException("系统异常，请联系后台管理员！");
        }

        return R.ok();
    }

    @Override
    public R saveYangluoLogisticsInfo(ErpLogisticsDto erpLogisticsDto, String userId, String createName) {
        try {
            ErpOrderStateContext erpOrderStateContext = new ErpOrderStateContext(new ProducingState(),
                    new LogisticsStateEntity(erpLogisticsDto)
            );
            R logistics = erpOrderStateContext.addLogistics(userId, createName);
            int code = (int) logistics.get("code");
            if (code == 500){
                return logistics;
            }
        }catch (Exception e){
            e.printStackTrace();
            throw new RRException("系统异常，请联系后台管理员！");
        }
        return R.ok();
    }

    @Override
    public R searchLogisticsInfoApi(Integer logiId, String logiNo) {
        // 查询物流公司编码
        String logiCom = this.baseMapper.selectLogiComById(logiId);
        R r = logisticsSearchApi.httpSearchLogistics(logiNo, logiCom);
        int code = (int) r.get("code");
        if (code != 0){
            return R.error(r.get("msg").toString());
        }

        LogisticsVo lv = (LogisticsVo) r.get("data");
        ErpLogisticsInforEntity erpLogisticsInfor = new ErpLogisticsInforEntity();
        erpLogisticsInfor.setLogiNo(logiNo);
        erpLogisticsInfor.setLogicCom(logiCom);
        erpLogisticsInfor.setLogicName(lv.getName());
        erpLogisticsInfor.setLogicStatus(lv.getCode());
        erpLogisticsInfor.setLogicState(String.valueOf(lv.getState()));
        List<Map<String, Object>> list = lv.getList();
        if (list != null && list.size() > 0){
            erpLogisticsInfor.setContent(JsonUtils.object2String(list));
        }else {
            erpLogisticsInfor.setContent(lv.getMsg());
        }
        erpLogisticsInfor.setUpdateDate(new Date());

        ErpLogisticsInforEntity erpLogisticsInforEntity = erpLogisticsInforService.selectByLogiNo(logiNo);
        if (erpLogisticsInforEntity == null){
            erpLogisticsInforService.insert(erpLogisticsInfor);
        }else {
            erpLogisticsInforService.updateById(erpLogisticsInfor);
        }

        return R.ok().put("erpLogisticsInfor", erpLogisticsInfor);
    }

    /**
     * 财务弃审
     * @param logiId
     * @return
     */
    @Override
    public R back(Integer logiId) {
        ErpLogisticsEntity erpLogisticsEntity = baseMapper.selectById(logiId);
        if(erpLogisticsEntity == null || erpLogisticsEntity.getLogisticFinanceStatus() == LogisticFinanceStatusEnum.PAYED.toInt()){
            return R.error("已付款状态不允许弃审！");
        }
        Map<String,Object> map = new HashMap<>();
        map.put("logisticFinanceStatus",LogisticFinanceStatusEnum.NOT_SUBMIT.toInt());
        map.put("updateName",UserUtils.getCurentUser().getUserId());
        baseMapper.updateByMap(map,logiId);

        Long orderId = erpLogisticsEntity.getOrderId();
        erpOrderLogService.insertOrderLog(orderId.toString(), "物流成本弃审，logiId：" + logiId);

        return R.ok();
    }

    /**
     * 录入成本
     */
    @Override
    public R enteringCost(CostFormVo costFormVo) {
        ErpLogisticsEntity erpLogisticsEntity = baseMapper.selectById(costFormVo.getLogiId());
        Integer logisticFinanceStatus = erpLogisticsEntity.getLogisticFinanceStatus();
        if(logisticFinanceStatus.intValue() != LogisticFinanceStatusEnum.NOT_SUBMIT.toInt()
                && logisticFinanceStatus.intValue() != LogisticFinanceStatusEnum.WAIT_AUDIT.toInt()){
            return R.error("当前状态不允许录入成本！");
        }else if(costFormVo.getLogiCost() <= 0){
            return R.error("物流成本需要大于零！");
        }
        Map<String,Object> map = new HashMap<>();
        map.put("logisticFinanceStatus",LogisticFinanceStatusEnum.WAIT_AUDIT.toInt());
        map.put("logiCost",costFormVo.getLogiCost());
        map.put("updateName",UserUtils.getCurentUser().getUsername());
        map.put("logiNo",costFormVo.getLogiNo());
        String logisticsName = costFormVo.getLogisticsName();
        if (StringUtils.isNotBlank(logisticsName)){
            map.put("logiCompany", logisticsName);
            LogisticsTypeEntity logisticsType = logisticsTypeService.selectOne(new EntityWrapper<LogisticsTypeEntity>().eq("logistics_name", logisticsName));
            if (logisticsType != null){
                map.put("logisticsId", logisticsType.getLogisticsId());
            }
        }
        baseMapper.updateByMap(map,costFormVo.getLogiId());

        Long orderId = erpLogisticsEntity.getOrderId();
        erpOrderLogService.insertOrderLog(orderId.toString(), "物流成本录入，logiId：" + costFormVo.getLogiId());

        return R.ok();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String exportLogistics(List<Map<String, Object>> mapData) {
        StringBuilder result = new StringBuilder();
        for (Map<String, Object> map:mapData){
            //订单号
            String orderId = StringUtil.toStr(map.get("订单号"));
            //物流单号
            String logiNo = StringUtil.toStr(map.get("物流单号"));
            //物流方式
            String logiCompany = StringUtil.toStr(map.get("物流方式"));
            //收件人
            String toPeople = StringUtil.toStr(map.get("收件人"));
            //收货地址
            String toAddress = StringUtil.toStr(map.get("收货地址"));
            //收货电话
            String toPhone = StringUtil.toStr(map.get("收货电话"));
            //发货人
            String fromPeople = StringUtil.toStr(map.get("发货人"));
            //发货地址
            String fromAddress = StringUtil.toStr(map.get("发货地址"));
            //发货时间
            Date sendTime = (Date) map.get("发货时间");

            //订单
            OrderInfoEntity orderInfoEntity = orderInfoService.selectById(orderId);
            if(orderInfoEntity == null){
                result.append(orderId + " 未查询到<br/>");
                continue;
            }else if(!"1".equals(orderInfoEntity.getPayStatus()) || orderInfoEntity.getPayed().doubleValue() <=0.0){
                result.append(orderId + " 未支付<br/>");
                continue;
            }

            ErpOrderEntity erpOrderEntity = erpOrderService.selectByNo(orderId);
            if(erpOrderEntity == null){
                result.append(orderId + " 未查询erp生产信息<br/>");
                continue;
            }
//            //物流方式
//            LogisticsTypeEntity logisticsType = logisticsTypeService.selectOne(
//                    new EntityWrapper<LogisticsTypeEntity>()
//                            .eq("logistics_name", logiCompany)
//            );
            if(erpOrderEntity == null){
                result.append(logiCompany + " 未录入物流方式<br/>");
                continue;
            }
            if(StringUtil.isNull(logiNo)){
                result.append(orderId + " 物流单号异常<br/>");
                continue;
            }

            // 物流单号查询
            R re = this.searchLogisticsInfoApi(101, logiNo);
            if(!"success".equals(re.get("msg"))){
                result.append(logiNo + " 未查询到物流信息<br/>");
                continue;
            }
            ErpLogisticsInforEntity erpLogisticsInforEntity = (ErpLogisticsInforEntity)re.get("erpLogisticsInfor");

            ErpLogisticsEntity erpLogisticsEntity = new ErpLogisticsEntity();
            erpLogisticsEntity.setOrderId(Long.parseLong(orderInfoEntity.getOrderId()));
            erpLogisticsEntity.setOrderNo(orderInfoEntity.getOrderId());
            erpLogisticsEntity.setSellerId(orderInfoEntity.getSupplierId().longValue());
            erpLogisticsEntity.setFromPeople(fromPeople);
            erpLogisticsEntity.setFromAddress(fromAddress);
            erpLogisticsEntity.setSendTime(sendTime);
            erpLogisticsEntity.setToPeople(toPeople);
            erpLogisticsEntity.setToAddress(toAddress);
            erpLogisticsEntity.setLogiNo(logiNo);
            erpLogisticsEntity.setLogiCompany(logiCompany);
            erpLogisticsEntity.setLogiRemark("批量导入阳逻发货数据");
            erpLogisticsEntity.setSendType(3);
            erpLogisticsEntity.setLogiType(2);
            erpLogisticsEntity.setCreateName("admin");
            erpLogisticsEntity.setToPeople(toPhone);

            erpLogisticsEntity.setLogisticsId("101");
            erpLogisticsService.insert(erpLogisticsEntity);

            Map<String,Object> orderUMap = new HashMap<>();
            orderUMap.put("shipStatus","1");
            orderUMap.put("shipTime",sendTime);
            // 签收
            if("3".equals(erpLogisticsInforEntity.getLogicState())){
                orderUMap.put("status","finish");
                orderUMap.put("receivedTime",DateUtils.format(new Date()));
            }
            orderInfoService.updateByMap(orderUMap,orderId);

            Map<String,Object> erpOrderUMap = new HashMap<>();
            // 签收
            if("3".equals(erpLogisticsInforEntity.getLogicState())){
                erpOrderUMap.put("productionStatus",ProductionStatusEnum.FINISH.toInt());
                erpOrderUMap.put("receivedTime",DateUtils.format(new Date()));
            }else{
                erpOrderUMap.put("productionStatus",ProductionStatusEnum.DELIVERED.toInt());
            }
            erpOrderUMap.put("shipStatus",ShipStatusEnum.shipped.toCode());
            erpOrderUMap.put("sendTime",DateUtils.format(sendTime));
            Date deliveryTime = DateUtils.addDateDays(sendTime,7);
            erpOrderUMap.put("deliveryTime",DateUtils.format(deliveryTime));
            erpOrderService.updateByMap(erpOrderUMap,erpOrderEntity.getOrderNo());

            List<ErpOrderItemEntity> erpOrderItemEntityList = erpOrderItemService.selectListByErpOrder(erpOrderEntity.getOrderNo());

            for (ErpOrderItemEntity erpOrderItemEntity:erpOrderItemEntityList){
                Map<String,Object> erpOrderItemUMap = new HashMap<>();
                erpOrderItemUMap.put("status",4);
                erpOrderItemService.updateByMap(erpOrderItemUMap,erpOrderItemEntity.getEoItemId());
            }

//            try {
//                Thread.sleep(100L);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
        }
        return  result.toString();
    }

    @Override
    public R updateLogisticsInfo(Integer logiId, String logiNo) {
        ErpLogisticsEntity erpLogisticsEntity = this.selectById(logiId);

        Map<String, Object> updateMap = new HashMap<>();
        updateMap.put("logiNo", logiNo);
        this.baseMapper.updateByMap(updateMap, logiId);

        Long orderId = erpLogisticsEntity.getOrderId();
        erpOrderLogService.insertOrderLog(orderId.toString(), "物流单号修改，logiId：" + logiId);

        return R.ok();
    }

    @Override
    public R deleteLogi(Integer logiId) {
        ErpLogisticsEntity erpLogistics = this.selectById(logiId);
        Integer logisticFinanceStatus = erpLogistics.getLogisticFinanceStatus();
        if (logisticFinanceStatus.intValue() == LogisticFinanceStatusEnum.PAYED.toInt()){
            return R.error("物流已报销");
        }

        Map<String, Object> updateMap = new HashMap<>();
        updateMap.put("delete", DeleteEnum.DELETE.toInt());
        this.baseMapper.updateByMap(updateMap, logiId);

        Long orderId = erpLogistics.getOrderId();
        erpOrderLogService.insertOrderLog(orderId.toString(), "物流删除，logiId：" + logiId);

        return R.ok();
    }

    @Override
    public R batchPayConfim(LogisticsPayDto logisticsPayDto) {
        String logiId = logisticsPayDto.getLogiId();
        String[] split = logiId.split(",");
        List<String> list = Arrays.asList(split);
        List<Integer> ids = new ArrayList<>(list.size());
        for (String str : list){
            ids.add(Integer.valueOf(str));
        }
        List<ErpLogisticsEntity> erpLogisticsEntities = this.baseMapper.selectBatchIds(ids);
        long count = erpLogisticsEntities.stream().filter(item -> item.getLogisticFinanceStatus().intValue() != LogisticFinanceStatusEnum.WATI_PAY.toInt()).count();
        if (count > 0){
            return R.error("请选择待付款状态单据");
        }

        Long userId = logisticsPayDto.getUserId();
        Date logiPaytime = logisticsPayDto.getLogiPaytime();
        String logiPayRemark = logisticsPayDto.getLogiPayRemark();
        Map<String,Object> updateMap = new HashMap<>();
        updateMap.put("logisticFinanceStatus",LogisticFinanceStatusEnum.PAYED.toInt());
        updateMap.put("updateName",userId.toString());
        updateMap.put("logiPaytime",logiPaytime);
        if(StringUtil.isNotEmpty(logiPayRemark)){
            updateMap.put("logiPayRemark",logiPayRemark.trim());
        }
        this.baseMapper.updateBatchByMap(updateMap, ids);

        for (ErpLogisticsEntity erpLogistics : erpLogisticsEntities){
            Integer loId = erpLogistics.getLogiId();
            Long orderId = erpLogistics.getOrderId();
            erpOrderLogService.insertOrderLog(orderId.toString(), "物流成本确认付款，logiId：" + loId);
        }

        return R.ok();
    }

    @Override
    public R batchAudit(Integer[] logiIds, Long userId) {
        List<Integer> ids = Arrays.asList(logiIds);
        List<ErpLogisticsEntity> erpLogisticsEntities = baseMapper.selectBatchIds(ids);
        long count = erpLogisticsEntities.stream().filter(item -> item.getLogisticFinanceStatus().intValue() != LogisticFinanceStatusEnum.WAIT_AUDIT.toInt()).count();
        if (count > 0){
            return R.error("请选择待审核状态单据");
        }

        Map<String,Object> updateMap = new HashMap<>();
        updateMap.put("logisticFinanceStatus", LogisticFinanceStatusEnum.WATI_PAY.toInt());
        updateMap.put("updateName", userId);

        baseMapper.updateBatchByMap(updateMap, ids);

        for (ErpLogisticsEntity erpLogistics : erpLogisticsEntities){
            Integer logiId = erpLogistics.getLogiId();
            Long orderId = erpLogistics.getOrderId();
            erpOrderLogService.insertOrderLog(orderId.toString(), "物流成本审核，logiId：" + logiId);
        }

        return R.ok();
    }

    @Override
    public R logiCostCount(Integer[] logiIds) {
        List<ErpLogisticsEntity> erpLogisticsEntities = this.selectBatchIds(Arrays.asList(logiIds));
        BigDecimal reduce = erpLogisticsEntities.stream().map(ErpLogisticsEntity::getLogiCost).reduce(BigDecimal.ZERO, BigDecimal::add);
        return R.ok().put("totalCost", reduce);
    }

    @Override
    public R importLogistics(MultipartFile multipartFile, Long userId, String username) {
        List<LogisticsImportDto> logisticsImportDtos = null;
        try {
            logisticsImportDtos = FileUtil.importExcel(multipartFile, 0, 1, LogisticsImportDto.class);
        }catch (Exception e){
            e.printStackTrace();
        }
        if (logisticsImportDtos.size() == 0){
            throw new RRException("未获取到物流信息");
        }

        StringBuilder stringBuilder = new StringBuilder();
        for (LogisticsImportDto logisticsImportDto: logisticsImportDtos){
            String orderId = logisticsImportDto.getOrderId();
            String logiNo = logisticsImportDto.getLogiNo();
            if (StringUtils.isEmpty(orderId) || StringUtils.isEmpty(logiNo)){
                continue;
            }
            OrderInfoEntity orderInfoEntity = orderInfoService.selectById(orderId);
            if (orderInfoEntity == null){
                stringBuilder.append("订单号[" + orderId + "] 快递单号[" + logiNo + "] 未查询到订单信息<br/>");
                continue;
            }
            ErpOrderEntity erpOrderEntity = erpOrderService.selectById(orderId);
            if (erpOrderEntity == null){
                stringBuilder.append("订单号[" + orderId + "] 快递单号[" + logiNo + "] 未查询到订单ERP生产信息<br/>");
                continue;
            }

            ErpLogisticsEntity erpLogisticsEntity = new ErpLogisticsEntity();
            erpLogisticsEntity.setOrderId(Long.parseLong(orderId));
            erpLogisticsEntity.setOrderNo(orderId);
            erpLogisticsEntity.setSellerId(orderInfoEntity.getSupplierId().longValue());
            erpLogisticsEntity.setFromPeople("ziyun");
            erpLogisticsEntity.setFromArea("湖北 武汉 江汉区");
            erpLogisticsEntity.setFromAddress("江汉区常青三路17B9-13");
            erpLogisticsEntity.setFromPhone("400-000-2519");
            erpLogisticsEntity.setToPeople(logisticsImportDto.getToPeople());
            erpLogisticsEntity.setToAddress(logisticsImportDto.getToAddress());
            erpLogisticsEntity.setToPhone(logisticsImportDto.getToPhone());
            StringBuilder sb = new StringBuilder();
            sb.append(logisticsImportDto.getToProvince()).append(" ").append(logisticsImportDto.getToCity()).append(" ").append(logisticsImportDto.getToArea());
            erpLogisticsEntity.setToArea(sb.toString());
            erpLogisticsEntity.setLogiNo(logiNo);
            erpLogisticsEntity.setLogisticsId("101");
            erpLogisticsEntity.setLogiCompany("百世快递");
            if (StringUtils.isNotBlank(logisticsImportDto.getLogRemark())){
                erpLogisticsEntity.setLogiRemark("批量导入：" + logisticsImportDto.getLogRemark());
            }else {
                erpLogisticsEntity.setLogiRemark("批量导入");
            }
            erpLogisticsEntity.setSendType(3);
            erpLogisticsEntity.setLogiType(2);
            erpLogisticsEntity.setCreateName(username);
            ErpLogisticsDto erpLogisticsDto = new ErpLogisticsDto();
            erpLogisticsDto.setErpLogisticsEntity(erpLogisticsEntity);
            List<ErpLogisticsItemEntity> erpLogisticsItemList = New.arrayList();
            erpLogisticsDto.setErpLogisticsItemList(erpLogisticsItemList);
            boolean save = false;
            try {
                R r = saveOrderLogisticsInfo(erpLogisticsDto, userId.toString(), username);
                int code = (int) r.get("code");
                if (code == 0){
                    save = true;
                }
            }catch (RRException e){
                e.printStackTrace();
            }
            if (!save){
                stringBuilder.append("订单号[" + orderId + "] 快递单号[" + logiNo + "] 物流信息保存异常<br/>");
            }else {
                stringBuilder.append("订单号[" + orderId + "] 快递单号[" + logiNo + "] 导入成功<br/>");
            }
        }

        if (!("").equals(stringBuilder.toString())){
            return R.error(stringBuilder.toString());
        }
        return R.ok();
    }

}
